商业化场景下,百度如何实践 Node.js 架构?
The following article is from 前端之巅 Author 冉叶兰
大前端商业化进程中,始终围绕着技术创新和工程优化这样一个双核主题,即如何从用户运营中获得商业价值的同时,又能不断探索和激发用户运营的新动力,两者相辅相成,共同保证大前端商业化向着更加成熟的方向发展。
在 Node.js 服务端升级过程中,如何选用 GraphQL 升级 RESTful API ?又如何利用新技术的优势和特点提高研发效率,降低运营成本?
百度原生商业部资深研发工程师尚飞将于 12 月 20~21 日举行的 GMTC 全球大前端技术大会 (深圳站) 上分享 《高效灵活易于演进的商业化场景 Node.js 架构实践》。InfoQ 在会前采访了尚飞老师,让我们一起来看看百度是如何在商业化场景中去实践 Node.js 架构的。
尚飞:2014 年,我在北邮毕业后进入阿里妈妈 MUX ,开始从事互联网商业广告的运作和研发工作。打趣地讲,如果当时有人问我“什么是互联网商业广告?”,我可能会反问他“你是指网页右下角那些弹窗,手机游戏顶部那些 GIF 图么?”,可见那时的我,虽然学习和娱乐大多依赖 PC ,手中的智能机也从 iPhone 3GS 换成了 HTC New One、华为 P6,但是对这个行业却没什么概念。回顾当时的行业发展状况,其实这也并不奇怪,那时阿里妈妈主要服务于淘宝 PC 营销,前后端业务主体都是 Java 实现的,用户体验方面非常简陋,也就造成了我对“弹窗”和“GIF 图”没感觉,一个对互联网商业广告一窍不通的校招生,这应该是对那时的我最准确的描述。
早在 2012 年 HTML5 规范定稿后,MUX 团队对“前后端分离”的诉求越来越高,并在 2013 年开始把 PC 前端业务从 Java 迁移到 JS 。2014 年,我加入 MUX 团队,虽说当时已经完成 9 成的迁移,但是由于当时技术的局限性,依旧遗留了若干令人非常抓狂的“临时方案”,其中 JS 组件化应属最难缠的一个,来自业界和团队的组件化方案可谓有利有弊,有的实现甚至要求在注释中编写 CSS 代码。如此形势下,团队投入专项人力打造了一系列符合团队诉求的 JS 组件化方案,产出了如 Magix、Brix 等优秀的前端组件化方案,这段经历也为我之后参与淘积木项目积累了宝贵的经验。
2015 年之后,我更多从事监控和基建类的工作。一来我对新技术非常感兴趣,而此类工作很适合爱去尝试新技术的人;二来我是真的懒,很难容忍一项工作长期占用人力成本。当时恰逢业界进入一个新的时代,不仅 Polymer、X-tag、Web Components、React 等新兴的 M(M)VC 框架让人眼花缭乱,而且 Node.js 也发布了第一个稳定版本 4.0.0,更有 Facebook 正式开源 GraphQL 规范,诸多新技术和新思路都在改变我们对前端的认知。在阿里的最后一年里,我参与打造淘积木,这是一款支持商家搭建个性化品牌效果和玩法的营销页构建平台,使用 Node.js 和类 React 组件化方案来打造前后端,打通了阿里妈妈多个营销平台和达摩盘(阿里妈妈一个广告数据分析平台),至今仍服务于淘宝、天猫众多商家。在阿里这段时间里,我先后参与了鹰眼、淘点金和淘积木等项目,探索并实践了很多新技术,不过由于受限于历史包袱,多数技术很难发挥其最大的作用,这也成为我在阿里的遗憾之一。
2017 年我来到百度原生商业推广部,负责广告数据 Node.js 接入层的研发,逐渐开始向全栈方向发展。从一线业务做起,大概花了 3 个月的时间全面了解百度原生商业技术的优势和不足,萌生了使用 GraphQL 升级 Node.js 接入层的想法。2018 年初,我开始解读 GraphQL 源码,结合业务现状,探索并尝试重构 Node.js 接入层,其中涉及诸如多层架构、编译工具、性能优化、中间件、日志监控和白盒测试等方方面面。历时 10 个月我完成近 20 万行代码的迁移和重构工作,新的 Node.js 接入层采用严谨的 GraphQL 对数据进行了清晰规范的描述,使用灵活的 ES6 组织业务逻辑,按业务关注点配以最契合的技术能力,形成一套各司其职、相辅相成的双轨编程体系,同时搭建起支持业务全貌可视化、测试流程开放化和监控定位自助化的研发 + 测试 + 监控平台。
尚飞: 在商业化场景下,使用 Node.js 架构主要期望提高团队以下几个方面的能力。
首先是快速响应需求,先人一步意味着更多的收益。回顾 Node.js 的发展进程,4 年时间从版本从 4.0 发展到 12.11,更新的速度非常快,始终与前端技术的发展保持同步,提供了强大易用的后端能力。如今,具备编写 Node.js 程序早已成为前端从业者的必备技能之一,大中规模的技术团队也普遍有意识地储备和培养 Node.js 工程师。当然,如此现状并不是证明前后端又不分离了,反而恰恰是商业化场景下的“前后端分离”成就了 Node.js 工程师可以大展拳脚了。分离的后端,负责更加底层和抽象的数据服务,诸如用户画像、实时竞价、训练模型、动态频控、反作弊等宏观和策略方面等。分离后的前端,负责更加表层和具体的数据服务和用户体验,诸如版本控制、行为收集、性能监控、溯源定位、交互更新等细节和体验方面等。后端的研发周期长,适合挖掘受客观因素影响较大的商业化价值。前端的研发周期短,适合响应受偶发因素影响较多的商业价值。
其次是低成本的平台化建设,使用 Node.js 架构不仅能够稳定支撑业务需求,而且也具备构建平台化的潜力,这种“双生”模式充分利用了前端从业者在用户体验方面的优势,商业化场景需要服务平台化这一利器,解放人力、完善工作流、提高沟通效率以及构建自助型服务等等。商机面前高效处理问题意味着减少损失,保护来之不易的变现渠道。
最后是开放式的技术氛围,挖掘商业化场景的最大价值,需要敏锐地洞察力,也需要强大的技术支撑,得益于活跃的开源社区,许多“轮子”都支持 Node.js 下使用,大大提高了前端从业者将想法付诸实现的能力。
尚飞: 引用官方的一段解释:GraphQL 是一种用于 API 的查询语言,也是一个满足数据查询的 Runtime ,不仅提供了一套易于理解的数据描述,而且支持更高效、强大和灵活的数据提供方式,没有任何冗余,也让 API 更容易地随业务发展而演进,还能用于构建强大的开发者工具。
声明式 API ,所见即所得,按需定制。
强大的类型系统提供易于理解的数据描述。
构建强大的开发者工具,内省系统支持代码即文档。
GraphQL 的内省系统不仅将 Schema 和注释生成可视化的文档,使得代码变更直接反映到最新文档,从而避免 RESTful 手工维护造成代码文档不一致的问题,而且支持构建如同 GraphiQL 的开发者工具,帮助开发者准确了解数据全貌,还能智能高亮提示潜在问题。
GraphQL 当然也有一些短板,相比 RESTful 在诸如控制最大查询深度、平衡查询复杂度权重、实现字段级缓存等方面需要前后端投入更多的成本,也正是由于这些问题,使得在现有架构体系中,GraphQL 还是很难全面替代 RESTful 的。一般地,后端技术选型还是以 RESTful 为首选,可以在其后应用 GraphQL 架设一个接入层,赋予 Node.js 工程师一个扩展空间,来满足前端对声明式 API 的渴求,由前端自治数据接口的灵活度。
尚飞: 应用 GraphQL 时面对两大技术挑战,其一是如何控制查询复杂度,其二是如何保持性能无损。
控制查询复杂度,这是应用 GraphQL 必须要解决的一个问题。通常而言,在生产环境下很难保证一个后端服务需要的数据都来自于单一的数据源,数据库、微服务、第三方 API 都可能作为若干数据片段的来源之一,那么实现统一向多源发送请求对稳定高效地应用 GraphQL 有着非常大的提升作用。综合考虑 GraphQL 的优缺点,同时鉴于客户端发版的不可变因素,我们在生产环境下,接入层并没有架设在前后端中间的位置,而是内嵌在一个后端服务之中接受单一数据源,作为一个内置功能集完成与 RESTful 的配合。这样并没有改变前端调用 API 的方式,但是将调用的灵活度以可枚举的状态控制在后端,最大程度保留了 GraphQL 除声明式 API 以外的其他优势,如强类型的 Schema、代码即文档、内省系统、开发者工具等强大能力。
性能瓶颈,源于 GraphQL 为了响应全部可能的请求,每次接到请求时都需要耗费 40+ms 以上去构建与之匹配的 ExecuteContext ,相比于 RESTful 的 10ms 左右的耗时,这样的性能下降是不可接受的。鉴于我们的接入层属于 IO 型服务,对内存的消耗很低,在可枚举的有限组合情况下,对 GraphQL 的源码稍作修改,利用好内存空间支持在服务启动时一次构建全部的 ExecuteContext 置于内存中待用,以空间复杂度换取时间复杂度,成功将平响时间保持在 10ms 以内。
尚飞: 大前端商业化的核心是在用户与客户连接的场景之下,并且在大前端的基础职责之上,进一步挖掘与发挥大前端的优势能力,提升用户与客户的连接效率。其中非常明确地指出了大前端商业化的一个特点,也是目标,即提升用户与客户的连接效率。不得不说,先人一步意为着更多的收益,考量一种商业化研发运营模式的流量变现实力,效率是一个非常重要的指标,而另一个与之密不可分的指标就是稳定,应用 GraphQL 对传统的 RESTful 进行升级,正是挖掘与发挥大前端在效率和稳定两方面优势的选择。
尚飞: 大前端商业化需要长期坚持在效率和稳定上的技术投入,但是仅此而已是万万不够的,应该更趋向于关注并挖掘商业化进程中众多“小细散”因素的价值,探索大前端技术(动态化、图形渲染,边缘 AI 等)的应用,淘沙般发现用户与客户之间的商机。
在移动互联网的大背景下,微服务、 NA 客户端等已经为大前端提供了非常多的立足空间,充分合理地利用好时代赋予我们的技术沃土,关注并探索那些从前“做不了,甚至被忽略”的领域。例如,利用好 NA 端能力和 AI 技术感知用户行为,捕获发散多变的用户注意力中所隐藏的兴趣线索,更精准地理解用户的潜商机。